<template>
  <el-dialog
    v-model="visible"
    :title="'手写板'"
    class="hand-sign-dialog"
    :show-close="true"
    :close-on-click-modal="false"
    :width="1000"
  >
    <div class="hand-sign-board">
      <div v-if="rowData?.drugName" style="position: absolute;  top: 20px;left: 50%;margin-left: -49px;">药品名：{{ rowData?.drugName }}</div>
      <canvas
        ref="canvasRef"
        class="sign-canvas"
        :class="{ signing: isDrawing }"
        :width="canvasWidth"
        :height="canvasHeight"
      ></canvas> 
      <div v-if="deviceInfo" class="device-info">
        {{ deviceInfo }}
      </div>
    </div>
    <div class="hand-sign-footer">
      <div class="footer-left">
        <el-button class="footer-btn orange" @click="clearCanvas"
          >重写</el-button
        >
        <el-button class="footer-btn orange" @click="cancel">撤销</el-button>
      </div>
      <div class="footer-right">
        <el-button class="footer-btn green" @click="confirm">确定</el-button>
        <!-- <el-button class="footer-btn green" @click="next">下一个</el-button> -->
      </div>
    </div>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, onBeforeUnmount, watch, nextTick } from 'vue';

/**
 * 笔触点接口
 */
interface StrokePoint {
  x: number;
  y: number;
  pressure: number;
  lineWidth: number;
  timestamp: number;
}

const props = defineProps<{ modelValue: boolean,rowData?: any }>();
const emit = defineEmits(['update:modelValue', 'confirm', 'next']);

const visible = ref(props.modelValue);
const rowData = ref<any>(props.rowData);

watch(() => props.rowData, (val) => {
  rowData.value = val
})


const canvasRef = ref<HTMLCanvasElement | null>(null);
const canvasWidth = 950;
const canvasHeight = 520;

let ctx: CanvasRenderingContext2D | null = null;
let isDrawing = false;
let lastX = 0;
let lastY = 0;

// 笔触设置
const baseLineWidth = 2;
const pressureSensitivity = 3;
const strokeColor = '#000000';

// 历史记录
let strokes: Array<Array<StrokePoint>> = [];
let currentStroke: Array<StrokePoint> = [];

// 设备信息
const deviceInfo = ref<string>('');

/**
 * 监听父组件传入的 modelValue 变化
 */
watch(
  () => props.modelValue,
  async (val) => {
    visible.value = val;
    if (val) {
      await nextTick();
      if (canvasRef.value) {
        ctx = canvasRef.value.getContext('2d');
        setupCanvas();
        resetCanvas();
        bindEvents();
      }
    } else {
      unbindEvents();
      deviceInfo.value = '';
    }
  }
);

/**
 * 监听 visible 变化，同步回父组件
 */
watch(visible, (val) => {
  if (val !== props.modelValue) {
    emit('update:modelValue', val);
    if (!val) {
      unbindEvents();
      deviceInfo.value = '';
    }
  }
});

/**
 * 设置 Canvas 配置
 */
const setupCanvas = () => {
  if (!ctx || !canvasRef.value) return;

  const dpr = window.devicePixelRatio || 1;
  const rect = canvasRef.value.getBoundingClientRect();

  // 设置实际渲染尺寸（考虑设备像素比）
  canvasRef.value.width = canvasWidth * dpr;
  canvasRef.value.height = canvasHeight * dpr;

  // 缩放绘图上下文
  ctx.scale(dpr, dpr);

  // 设置绘图样式
  ctx.lineCap = 'round';
  ctx.lineJoin = 'round';
};

/**
 * 重置 Canvas
 */
const resetCanvas = () => {
  if (ctx && canvasRef.value) {
    ctx.clearRect(0, 0, canvasWidth, canvasHeight);
    ctx.fillStyle = 'transparent';
    ctx.fillRect(0, 0, canvasWidth, canvasHeight);
  }
};

/**
 * 获取 Canvas 坐标
 */
const getCanvasPos = (e: PointerEvent): { x: number; y: number } => {
  const rect = canvasRef.value?.getBoundingClientRect();
  if (!rect) return { x: 0, y: 0 };

  const clientX = e.clientX;
  const clientY = e.clientY;

  return {
    x: clientX - rect.left,
    y: clientY - rect.top,
  };
};

/**
 * 开始绘制
 */
const startDrawing = (e: PointerEvent) => {
  if (!ctx) return;

  isDrawing = true;
  const { x, y } = getCanvasPos(e);
  lastX = x;
  lastY = y;
  currentStroke = [];

  // 显示设备信息
  const deviceTypeMap: Record<string, string> = {
    pen: '手写笔（支持压感）',
    mouse: '鼠标',
    touch: '触摸',
  };
  deviceInfo.value = `当前输入设备: ${
    deviceTypeMap[e.pointerType] || e.pointerType
  }`;
};

/**
 * 绘制
 */
const draw = (e: PointerEvent) => {
  if (!isDrawing || !ctx) return;

  e.preventDefault();

  const { x, y } = getCanvasPos(e);

  // 获取压感值（手写笔支持，鼠标/触摸默认 0.5）
  const pressure = e.pressure || 0.5;

  // 根据压感计算线宽
  const lineWidth = baseLineWidth + pressure * pressureSensitivity;

  // 绘制线段
  ctx.beginPath();
  ctx.moveTo(lastX, lastY);
  ctx.lineTo(x, y);
  ctx.strokeStyle = strokeColor;
  ctx.lineWidth = lineWidth;
  ctx.stroke();

  // 记录笔触点
  currentStroke.push({
    x,
    y,
    pressure,
    lineWidth,
    timestamp: Date.now(),
  });

  lastX = x;
  lastY = y;
};

/**
 * 结束绘制
 */
const stopDrawing = () => {
  if (isDrawing && currentStroke.length > 0) {
    strokes.push([...currentStroke]);
  }
  isDrawing = false;
  currentStroke = [];
};

/**
 * 绑定事件
 */
const bindEvents = () => {
  if (!canvasRef.value) return;

  canvasRef.value.addEventListener('pointerdown', startDrawing);
  canvasRef.value.addEventListener('pointermove', draw);
  canvasRef.value.addEventListener('pointerup', stopDrawing);
  canvasRef.value.addEventListener('pointerleave', stopDrawing);

  // 禁用默认触摸行为
  canvasRef.value.style.touchAction = 'none';
};

/**
 * 解绑事件
 */
const unbindEvents = () => {
  if (!canvasRef.value) return;

  canvasRef.value.removeEventListener('pointerdown', startDrawing);
  canvasRef.value.removeEventListener('pointermove', draw);
  canvasRef.value.removeEventListener('pointerup', stopDrawing);
  canvasRef.value.removeEventListener('pointerleave', stopDrawing);
};

/**
 * 重绘所有笔触
 */
const redraw = () => {
  if (!ctx) return;

  resetCanvas();

  strokes.forEach((stroke) => {
    stroke.forEach((point, index) => {
      if (index === 0 || !ctx) return;

      const prevPoint = stroke[index - 1];
      if (!prevPoint) return;

      ctx.beginPath();
      ctx.moveTo(prevPoint.x, prevPoint.y);
      ctx.lineTo(point.x, point.y);
      ctx.strokeStyle = strokeColor;
      ctx.lineWidth = point.lineWidth;
      ctx.stroke();
    });
  });
};

/**
 * 清空画布
 */
const clearCanvas = () => {
  resetCanvas();
  strokes = [];
  currentStroke = [];
};

/**
 * 撤销上一笔
 */
const cancel = () => {
  if (strokes.length > 0) {
    strokes.pop();
    redraw();
  }
};

/**
 * 确认签名
 */
const confirm = () => {
  if (!canvasRef.value || strokes.length === 0) {
    ElMessage.warning('请先签名');
    return;
  }

  const dataUrl = canvasRef.value.toDataURL('image/png');
  emit('confirm', dataUrl);
  emit('update:modelValue', false);
};

/**
 * 下一个
 */
const next = () => {
  if (!canvasRef.value) return;

  emit('next', canvasRef.value.toDataURL('image/png'));
  clearCanvas();
};

/**
 * 组件卸载时清理
 */
onBeforeUnmount(() => {
  unbindEvents();
});
</script>
<style >
  .hand-sign-dialog .el-dialog__header.show-close{
    display: flex;
    justify-content: left;
  }

</style>
<style scoped>
.hand-sign-dialog >>> .el-dialog__body {
  padding: 0 0 24px 0;
}
.hand-sign-board {
  background: #ddd;
  border-radius: 2px;
  min-height: 520px;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}
.sign-canvas {
  width: 950px;
  height: 520px;
  background: transparent;
  border-radius: 2px;
  display: block;
  cursor: crosshair;
  border: 2px solid #e5e7eb;
  transition: border-color 0.2s ease;
}
.sign-canvas.signing {
  border-color: #3b82f6;
}
.device-info {
  position: absolute;
  top: 10px;
  left: 10px;
  padding: 6px 12px;
  background: rgba(59, 130, 246, 0.9);
  color: #fff;
  border-radius: 4px;
  font-size: 14px;
  pointer-events: none;
  z-index: 10;
}
.hand-sign-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 0px 0 0px;
}
.footer-left {
  display: flex;
  gap: 12px;
}
.footer-right {
  display: flex;
  gap: 12px;
}
.footer-btn {
  min-width: 68px;
  height: 36px;
  font-size: 16px;
  border-radius: 4px;
  font-weight: 500;
  padding: 0 18px;
}
.footer-btn.orange {
  color: #faad14;
  border: 1.5px solid #faad14;
  background: #fff;
}
.footer-btn.orange:hover {
  background: #fffbe6;
}
.footer-btn.green {
  color: #fff;
  background: #18b3ab;
  border: none;
}
.footer-btn.green:hover {
  background: #13a39a;
}
</style>
